//! @Author: DengLibin
//! @Date: Create in 2023-12-15 11:07:21
//! @Description: KNN算法
//! K近邻算法，即是给定一个训练数据集，对新的输入实例，在训练数据集中找到与该实例最邻近的K个实例，这K个实例的多数属于某个类，就把该输入实例分类到这个类中

use std::{collections::HashMap, sync::Arc};

use log::info;

use crate::global::{self, GlobalResult};

//knn算法，k的取值
const K: usize = 20;

/// @Author: DengLibin
/// @Date: Create in 2023-12-15 11:08:08
/// @Description:
pub async fn run() -> GlobalResult<()> {
    info!("读取数据集");
    let lines = read_data("./data_set/knn/iris.txt").await?;

    info!("获取样本数据");
    //样本
    let examples = lines2structs(&lines).await?;
    println!("样本如下:");
    for e in examples.iter() {
        println!("{},{},{},{}--------{}", e.v[0], e.v[1],e.v[2],e.v[3],  e.cat);
    }
    drop(lines);

    //根据已知属性值和样本推断类型
    let cat = predict([6.2_f32, 2.2_f32, 4.5_f32, 1.5_f32], examples).await?;
    println!("预测结果：{}", cat);
    Ok(())
}

/// @Author: DengLibin
/// @Date: Create in 2023-12-15 11:20:31
/// @Description: 读取数据
async fn read_data(data_path: &str) -> GlobalResult<Vec<String>> {
    let mut v: Vec<String> = Vec::new();
    let r = rust_common::tokio_file::read_by_line(data_path, |line| {
        v.push(line);
    })
    .await;
    global::check_result(r)?;
    Ok(v)
}

/// @Author: DengLibin
/// @Date: Create in 2023-12-15 12:16:49
/// @Description: 行字符串转结构体
async fn lines2structs(lines: &Vec<String>) -> GlobalResult<Vec<IrisType>> {
    let mut iris: Vec<IrisType> = Vec::new();
    for line in lines {
        let o = line2struct(line).await?;
        iris.push(o);
    }
    Ok(iris)
}

/// @Author: DengLibin
/// @Date: Create in 2023-12-15 12:01:26
/// @Description: 将一行数据转换成结构
async fn line2struct(line: &String) -> GlobalResult<IrisType> {
    let splits = line.split(",");
    let mut o = IrisType {
        v: [0_f32; 4],
        cat: "".into(),
    };
    let mut i: usize = 0;
    for item in splits {
        //属性值
        if i < 4_usize {
            let x = item.parse::<f32>();
            let x = global::check_result(x)?;
            o.v[i] = x;
        }
        //类别
        if i == 4_usize {
            o.cat = item.into();
        }

        i += 1;
    }

    return Ok(o);
}

/// @Author: DengLibin
/// @Date: Create in 2023-12-15 12:25:06
/// @Description: 预测类型
async fn predict(v: [f32; 4], examples: Vec<IrisType>) -> GlobalResult<String> {
    let mut handlers = Vec::new();
    let v = Arc::from(v);

    //存一下对象
    let mut examples_new = Vec::new();

    let mut index: usize = 0;
    for item in examples {
        let ai = Arc::from(item);
        examples_new.push(ai.clone());
        //异步计算
        let f = tokio::spawn(distance(v.clone(), index, ai.clone()));
        index += 1;
        handlers.push(f);
    }
    //获取结果
    let mut dis_s = Vec::new();
    for h in handlers {
        let r = h.await;
        let dis = global::check_result(r)?;
        let dis = global::check_result(dis)?;

        //保存和样本的距离
        dis_s.push((examples_new[dis.0].clone(), dis.1));
    }
    //排序
    // dis_s.sort_by(|f1, f2|{
    //     let f =  f1 - f2;
    //     if f == 0_f32 {
    //         return Ordering::Equal;
    //     }
    //     if f > 0_f32 {
    //         return Ordering::Greater;
    //     }
    //     return Ordering::Less;
    // });

    println!("和样本距离如下:");
    for d in dis_s.iter() {
        println!("{},{},{},{}--------{}-------distance:{}", d.0.v[0], d.0.v[1],d.0.v[2],d.0.v[3],  d.0.cat, d.1);
    }

    //排序，只排前K个
    select_sort_top_asc(&mut dis_s, K);

    println!("按距离排序后:");
    for d in dis_s.iter() {
        println!("{},{},{},{}--------{}-------distance:{}", d.0.v[0], d.0.v[1],d.0.v[2],d.0.v[3],  d.0.cat, d.1);
    }

    //前k个，哪个分类最多
    //分类计数
    let mut count_map: HashMap<String, usize> = HashMap::new();

    //防止越界
    let mut n = K;
    if n > dis_s.len() {
        n = dis_s.len();
    }
    //计数统计
    for i in 0..n {
        let cat = &(dis_s[i].0.as_ref().cat);
        let count = count_map.entry(cat.into()).or_insert(0_usize);
        let x = *count;
        *count = x + 1;
    }
    println!("前{}个分类计数:", n);
    for m in count_map.iter() {
        println!("{}------{}", m.0, m.1);
    }


    //找出最多的那个分类
    let mut cat = "".into();
    let mut max_count: usize = 0;
    for m in count_map.into_iter() {
        if m.1 > max_count {
            max_count = m.1;
            cat = m.0;
        }
    }

    Ok(cat)
}

/// @Author: DengLibin
/// @Date: Create in 2023-12-15 13:40:22
/// @Description: 计算距离
async fn distance(
    v: Arc<[f32; 4]>,
    index: usize,
    iris: Arc<IrisType>,
) -> GlobalResult<(usize, f32)> {
    let mut dis_square: f32 = 0_f32;
    for i in 0..4 {
        let x = (v[i] - iris.v[i]).abs().powi(2);
        dis_square += x;
    }

    Ok((index, f32::sqrt(dis_square)))
}
/// @Author: DengLibin
/// @Date: Create in 2023-12-15 14:28:50
/// @Description: 选择排序 排前n个
fn select_sort_top_asc(mv: &mut Vec<(Arc<IrisType>, f32)>, mut n: usize) {
    //防止越界
    if n > mv.len() {
        n = mv.len();
    }
    for i in 0..n {
        for j in (i + 1)..mv.len() {
            //小的放前面
            if mv[j].1 < mv[i].1 {
                let temp = mv[j].clone();
                mv[j] = mv[i].clone();
                mv[i] = temp;
            }
        }
    }
}

struct IrisType {
    v: [f32; 4], //属性值向量，4个属性值
    cat: String, //对应的分类
}
